package ru.spbu.math.android.cbrf.charts;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import math.spbu.ru.historycharts.IDataProvider;
import math.spbu.ru.historycharts.model.DatePoint;
import math.spbu.ru.historycharts.model.XYMultipleSeriesDataset;
import math.spbu.ru.historycharts.model.XYSeries;
import math.spbu.ru.historycharts.renderer.PointStyle;
import math.spbu.ru.historycharts.renderer.XYMultipleSeriesRenderer;
import math.spbu.ru.historycharts.renderer.XYSeriesRenderer;
import ru.spbu.math.android.cbrf.dataprovider.ProviderManager;
import ru.spbu.math.android.cbrf.model.Rate;
import android.graphics.Color;
import android.util.Log;

public class DataProvider implements IDataProvider {

	private static XYMultipleSeriesRenderer mainRenderer;
	private static XYMultipleSeriesDataset mainDataset;
	private ChartsActivity ca;
	private String rateTypeID;
	private Calendar dateStart, dateEnd;

	public DataProvider(ChartsActivity ca, String RateTypeID) {
		this.ca = ca;
		this.rateTypeID = RateTypeID;

		dateEnd = new GregorianCalendar();
		dateStart = new GregorianCalendar();
		dateStart.set(Calendar.DAY_OF_MONTH,
				dateStart.get(Calendar.DAY_OF_MONTH) - 30);
				
		ArrayList<ArrayList<DatePoint>> dateList = new ArrayList<ArrayList<DatePoint>>();
		try{
		dateList.add((ArrayList<DatePoint>) getDinamicRateList(
				dateStart.getTimeInMillis(), dateEnd.getTimeInMillis()));
		}catch (Exception e) {
			ca.error();
		}
		
		mainDataset = buildDateDataset(getTitles(), dateList);
		mainRenderer = buildRenderer(getTitles().size());		
	}

	public List<DatePoint> getDinamicRateList(long start, long end)throws NullPointerException  {
		ProviderManager provider = ProviderManager.getInstance(ca);

		Calendar endDate = new GregorianCalendar();
		Calendar startDate = new GregorianCalendar();
		startDate.setTimeInMillis(start);
		endDate.setTimeInMillis(end);
		List<Rate> rateList = provider
		.getDynamicRates(rateTypeID, startDate.getTime(),
				endDate.getTime());
		
		if(rateList == null) {		
			Log.d("DataProvider", "" +rateList);
			throw new NullPointerException();
		}
		
		ArrayList<DatePoint> temp = convertToListDatePoint(rateList);
		return temp;
	}

	@Override
	public List<String> getTitles() {
		ProviderManager provider = ProviderManager.getInstance(ca);
		ArrayList<String> al = new ArrayList<String>(1);
		String name = provider.getRateTypeByExternalId(rateTypeID).getSource()
				.getName();
		al.add(name);
		return al;
	}

	public XYMultipleSeriesRenderer getRenderer() {
		return mainRenderer;
	}

	public XYMultipleSeriesDataset getDataset() {
		return mainDataset;
	}

	/**
	 * Builds an XY multiple time dataset using the provided values.
	 */
	public XYMultipleSeriesDataset buildDateDataset(List<String> titles,
			ArrayList<ArrayList<DatePoint>> datePoints) {
		XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
		int length = titles.size();
		for (int i = 0; i < length; i++) {
			XYSeries series = new XYSeries(titles.get(i));
			List<DatePoint> dpList = datePoints.get(i);
			series.addListInEnd(dpList);
			dataset.addSeries(series);
		}
		return dataset;
	}

	/**
	 * Builds an XY multiple series renderer
	 */
	public XYMultipleSeriesRenderer buildRenderer(int count) {
		XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
	
		ProviderManager provider = ProviderManager.getInstance(ca);
		for (int i = 0; i < count; i++) {
			XYSeriesRenderer r = new XYSeriesRenderer();
			r.setColor(getRandomColor());
			r.setPointStyle(PointStyle.CIRCLE);
			r.setFillPoints(true);
			renderer.addSeriesRenderer(r);
		}
		renderer.setXAxisMax(getDataset().getMaxX());
		renderer.setXAxisMin(getDataset().getMinX());
		String targetName = provider.getRateTypeByExternalId(rateTypeID)
				.getTarget().getName();
		renderer.setYTitle(targetName);
		return renderer;
	}

	// TODO
	private int getRandomColor() {
		return Color.RED;
	}

	private ArrayList<DatePoint> convertToListDatePoint(List<Rate> in) {
		if (in == null) return null;
		ArrayList<DatePoint> out = new ArrayList<DatePoint>(in.size());
		for (Rate r : in) {
			out.add(new DatePoint(r.getDate(), r.getValue()));
		}
		return out;
	}

	@Override
	public DatePoint getDateValueByXY(double x, double y) {
		DatePoint date = null;

		XYSeries d = mainDataset.getSeriesAt(0);
		int first = d.getFirst(), last = d.getLast();
		float[] vector = d.getPointsVector();
		double eps = 5;
		Log.d("BNV", "x= " + x + " y= " + y);
		for (int i = first * 2; (i < last * 2) && (vector[i] < x + eps); i += 2)
		{			
			if ((vector[i] < x + eps) && (vector[i] > x - eps))
				if ((vector[i + 1] < y + eps) && (vector[i + 1] > y - eps))
					date = d.get(i/2);
		}
		return date;
	}

	public String getDateFormat() {
		return DATA_FORMAT;
	}

	public void setDateFormat(String format) {
		DATA_FORMAT = format;
	}

	private String DATA_FORMAT = "dd MMM";
}
